home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvitops / tpic.c < prev    next >
C/C++ Source or Header  |  1991-01-25  |  13KB  |  550 lines

  1. static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/tpic.c,v 1.4 90/08/14 13:03:50 jjc Rel $";
  2.  
  3. #include "dvitops.h"
  4.  
  5. #ifdef TPIC_SUPPORT
  6.  
  7. /* Dotted lines look a bit anaemic; so we add this many milli-inches to
  8.    the pen size of a dotted line. */
  9.  
  10. #define DOTTED_LINE_WIDTH_ADDITION 3
  11.  
  12. /* flags in tpic_object is or'ed from these */
  13.  
  14. #define ARC 1
  15. #define SPLINE 2
  16. #define SHADED 4
  17. #define INVISIBLE 8
  18. #define DOTTED 16
  19. #define DASHED 32
  20.  
  21. struct point {
  22.     integer x;
  23.     integer y;
  24. };
  25.  
  26. struct tpic_object {
  27.     struct tpic_object *next;
  28.     integer h, v;
  29.     int region;
  30.     unsigned flags;
  31.     integer pen_size;
  32.     float shade;
  33.     union {
  34.         struct {
  35.             float dash_width;
  36.             int npoints;
  37.             struct point point_vector[2]; /* may be bigger than this */
  38.         } p;
  39.         struct {
  40.             integer cx;
  41.             integer cy;
  42.             integer rx;
  43.             integer ry;
  44.             float s;
  45.             float e;
  46.         } a;
  47.     } u;
  48. };
  49.  
  50. #ifdef PROTO
  51. static void draw_path(FILE *psfp, double sc, integer h, integer v,
  52.                       struct point *pv, int np, int closed);
  53. static void draw_spline(FILE *psfp, double sc, integer h, integer v,
  54.                       struct point *pv, int np);
  55. static void draw_ellipse(FILE *psfp, double sc, integer h, integer v,
  56.                          integer cx, integer cy, integer rx, integer ry);
  57. static void draw_arc(FILE *psfp, double sc, integer h, integer v,
  58.                      integer cx, integer cy, integer r, double s, double e);
  59. #else
  60. static void draw_path();
  61. static void draw_spline();
  62. static void draw_ellipse();
  63. static void draw_arc();
  64. #endif
  65.  
  66. struct tpic_object *tpic_object_list = NULL;
  67.  
  68. #define TPIC_CODE(c1, c2) (((unsigned char)(c1) << 8) + (unsigned char)(c2))
  69.  
  70. /* return 1 if it was a tpic_special, 0 otherwise */
  71.  
  72. int tpic_special(pass, arg, x, y)
  73. int pass;
  74. char *arg;
  75. integer x, y;
  76. {
  77.     static integer current_pen_size = 8;
  78.     static unsigned tpic_flags = 0;
  79.     static float shade = 0.0;
  80.     static int npoints = 0;
  81.     static int maxpoints = 0;
  82.     static struct point *point_vector = 0;
  83.     double dash_width;
  84.     int complete = 0;
  85.     while (*arg == ' ')
  86.         arg++;
  87.     if (arg[0] == '\0' || arg[1] == '\0'
  88.         || (arg[2] != ' ' && arg[2] != '\0'))
  89.         return 0;
  90.     if (pass != PASS2) {
  91.         switch (TPIC_CODE(arg[0], arg[1])) {
  92.         case TPIC_CODE('p', 'n'):
  93.         case TPIC_CODE('p', 'a'):
  94.         case TPIC_CODE('s', 'p'):
  95.         case TPIC_CODE('d', 'a'):
  96.         case TPIC_CODE('d', 't'):
  97.         case TPIC_CODE('i', 'p'):
  98.         case TPIC_CODE('f', 'p'):
  99.         case TPIC_CODE('i', 'a'):
  100.         case TPIC_CODE('a', 'r'):
  101.         case TPIC_CODE('s', 'h'):
  102.         case TPIC_CODE('w', 'h'):
  103.         case TPIC_CODE('b', 'k'):
  104.             return 1;
  105.         default:
  106.             /* it's not a tpic special */
  107.             return 0;
  108.         }
  109.     }
  110.     switch (TPIC_CODE(arg[0], arg[1])) {
  111.     case TPIC_CODE('p', 'n'):
  112.     {
  113.         long n;
  114.         if (sscanf(arg + 2, "%ld", &n) != 1) {
  115.             message(ERROR, "bad argument to pn special");
  116.             return 1;
  117.         }
  118.         current_pen_size = n;
  119.         break;
  120.     }
  121.     case TPIC_CODE('p', 'a'):
  122.     {
  123.         long x, y;
  124.         if (sscanf(arg + 2, "%ld %ld", &x, &y) != 2) {
  125.             message(ERROR, "bad arguments to pa special");
  126.             return 1;
  127.         }
  128.         if (npoints >= maxpoints) {
  129.             if (maxpoints == 0) {
  130.                 point_vector = (struct point *)
  131.                     malloc((maxpoints = 5)*sizeof(struct point));
  132.                 if (point_vector == NULL)
  133.                     out_of_memory();
  134.             }
  135.             else {
  136.                 point_vector = (struct point *)
  137.                     realloc((char *)point_vector,
  138.                             sizeof(struct point)*(maxpoints *= 2));
  139.                 if (point_vector == NULL)
  140.                     out_of_memory();
  141.             }
  142.         }
  143.         point_vector[npoints].x = x;
  144.         point_vector[npoints].y = y;
  145.         npoints++;
  146.         break;
  147.     }
  148.     case TPIC_CODE('s', 'p'):
  149.     {
  150.         float f;
  151.         if (sscanf(arg + 2, "%f", &f) == 1 && f != 0.0) {
  152.             if (f > 0.0) {
  153.                 tpic_flags |= DASHED;
  154.                 dash_width = f;
  155.             }
  156.             else {
  157.                 tpic_flags |= DOTTED;
  158.                 dash_width = -f;
  159.             }
  160.         }
  161.         tpic_flags |= SPLINE;
  162.         goto path;
  163.     }
  164.     case TPIC_CODE('d', 'a'):
  165.     {
  166.         float f;
  167.         if (sscanf(arg + 2, "%f", &f) != 1) {
  168.             message(ERROR, "bad argument to da special");
  169.             return 1;
  170.         }
  171.         tpic_flags |= DASHED;
  172.         dash_width = f;
  173.         goto path;
  174.     }
  175.     case TPIC_CODE('d', 't'):
  176.     {
  177.         float f;
  178.         if (sscanf(arg + 2, "%f", &f) != 1) {
  179.             message(ERROR, "bad argument to dt special");
  180.             return 1;
  181.         }
  182.         tpic_flags |= DOTTED;
  183.         dash_width = f;
  184.         goto path;
  185.     }
  186.     case TPIC_CODE('i', 'p'):
  187.         tpic_flags |= INVISIBLE;
  188.         /* fall through */
  189.     case TPIC_CODE('f', 'p'):
  190.     path:
  191.     {
  192.         struct tpic_object *p;
  193.         size_t sz = sizeof(struct tpic_object);
  194.         if (npoints > 2)
  195.             sz += sizeof(struct point)*(npoints - 2);
  196.         p = (struct tpic_object *)malloc(sz);
  197.         if (p == NULL)
  198.             out_of_memory();
  199.         p->flags = tpic_flags;
  200.         if (tpic_flags & (DOTTED|DASHED))
  201.             p->u.p.dash_width = dash_width;
  202.         tpic_flags = 0;
  203.         memcpy((char *)p->u.p.point_vector, (char *)point_vector,
  204.                npoints*sizeof(struct point));
  205.         p->u.p.npoints = npoints;
  206.         npoints = 0;
  207.         p->next = tpic_object_list;
  208.         tpic_object_list = p;
  209.         complete = 1;
  210.         break;
  211.     }
  212.     case TPIC_CODE('i', 'a'):
  213.         tpic_flags |= INVISIBLE;
  214.         /* fall through */
  215.     case TPIC_CODE('a', 'r'):
  216.     {
  217.         struct tpic_object *p;
  218.         long x, y;
  219.         long rx, ry;
  220.         float s, e;
  221.         if (sscanf(arg + 2, "%ld %ld %ld %ld %f %f",
  222.                    &x, &y, &rx, &ry, &s, &e) != 6) {
  223.             if (arg[0] == 'i')
  224.                 message(ERROR, "bad argument to ia special");
  225.             else
  226.                 message(ERROR, "bad argument to ar special");
  227.             return 1;
  228.         }
  229.         p = (struct tpic_object *)malloc(sizeof(struct tpic_object));
  230.         if (p == NULL)
  231.             out_of_memory();
  232.         p->flags = ARC|tpic_flags;
  233.         tpic_flags = 0;
  234.         p->u.a.cx = x;
  235.         p->u.a.cy = y;
  236.         p->u.a.rx = rx;
  237.         p->u.a.ry = ry;
  238.         p->u.a.s = s;
  239.         p->u.a.e = e;
  240.         p->next = tpic_object_list;
  241.         tpic_object_list = p;
  242.         complete = 1;
  243.         break;
  244.     }
  245.     case TPIC_CODE('s', 'h'):
  246.     {
  247.         float f;
  248.         if (sscanf(arg + 2, "%f", &f) != 1)
  249.             f = 0.5;
  250.         tpic_flags |= SHADED;
  251.         shade = f;
  252.         break;
  253.     }
  254.     case TPIC_CODE('w', 'h'):
  255.         tpic_flags |= SHADED;
  256.         shade = 0.0;
  257.         break;
  258.     case TPIC_CODE('b', 'k'):
  259.         tpic_flags |= SHADED;
  260.         shade = 1.0;
  261.         break;
  262.     default:
  263.         /* it's not a tpic special */
  264.         return 0;
  265.     }
  266.     if (complete) {
  267.         /* we just completed an object, so fill in some details */
  268.         tpic_object_list->h = x;
  269.         tpic_object_list->v = y;
  270.         tpic_object_list->region = current_region;
  271.         tpic_object_list->pen_size = current_pen_size;
  272.         if (tpic_object_list->flags & DOTTED)
  273.             tpic_object_list->pen_size += DOTTED_LINE_WIDTH_ADDITION;
  274.         if (tpic_object_list->flags & SHADED)
  275.             tpic_object_list->shade = shade;
  276.     }
  277.     return 1;
  278. }
  279.  
  280. #define round(d) ((long)((d) + 0.5))
  281.  
  282.  
  283. void p_tpic_list(psfp, page)
  284. FILE *psfp;
  285. struct page_info *page;
  286. {
  287.     int r = NO_REGION;
  288.     integer ox = 0, oy = 0;
  289.     integer ps = -1;
  290.     double sc = (254.0*page->den)/page->num;
  291.     struct tpic_object *p = tpic_object_list;
  292.     if (p == NULL)
  293.         return;
  294.     /* reverse tpic_object_list */
  295.     tpic_object_list = NULL;
  296.     while (p != NULL) {
  297.         struct tpic_object *tem = p;
  298.         p = p->next;
  299.         tem->next = tpic_object_list;
  300.         tpic_object_list = tem;
  301.     }
  302.     fputs("BO TP\n", psfp);
  303.     while (tpic_object_list != NULL) {
  304.         p = tpic_object_list;
  305.         if (p->region != r) {
  306.             if (r != NO_REGION)
  307.                 fputs("GR\n", psfp);
  308.             if (p->region != NO_REGION) {
  309.                 fputs("GS\n", psfp);
  310.                 do_transform(p->region, &ox, &oy, psfp);
  311.             }
  312.             else
  313.                 ox = oy = 0;
  314.             r = p->region;
  315.         }
  316.         p->h -= ox;
  317.         p->v -= oy;
  318.         if (p->pen_size != ps) {
  319.             ps = p->pen_size;
  320.             put_dim(round(ps*sc), psfp);
  321.             fputs(" LW\n", psfp);
  322.         }
  323.         if (p->flags & ARC) {
  324.             integer cx, cy, rx, ry;
  325.             double s, e;
  326.             cx = p->u.a.cx;
  327.             cy = p->u.a.cy;
  328.             rx = p->u.a.rx;
  329.             ry = p->u.a.ry;
  330.             s = p->u.a.s;
  331.             e = p->u.a.e;
  332.             if (e - s >= M_PI*2.0) {
  333.                 if (p->flags & SHADED) {
  334.                     if (p->shade != 1.0)
  335.                         fprintf(psfp, "%g SG\n", 1 - p->shade);
  336.                     draw_ellipse(psfp, sc, p->h, p->v, cx, cy, rx, ry);
  337.                     fputs("FI\n", psfp);
  338.                     if (p->shade != 1.0)
  339.                         fputs("0 SG\n", psfp);
  340.                 }
  341.                 if (!(p->flags & INVISIBLE)) {
  342.                     draw_ellipse(psfp, sc, p->h, p->v, cx, cy, rx, ry);
  343.                     fputs("ST\n", psfp);
  344.                 }
  345.             }
  346.             else {
  347.                 if (rx != ry)
  348.                     message(WARNING, "open arc with rx != ry");
  349.                 draw_arc(psfp, sc, p->h, p->v, cx, cy, rx, s, e);
  350.                 fputs("ST\n", psfp);
  351.             }
  352.         }
  353.         else {
  354.             int np = p->u.p.npoints;
  355.             struct point *pv = p->u.p.point_vector;
  356.             double dw = p->u.p.dash_width*1000.0;
  357.             if (p->flags & SPLINE) {
  358.                 if (p->flags & DASHED) {
  359.                     put_dim(round(sc*dw), psfp);
  360.                     putc(' ', psfp);
  361.                     put_dim(round(sc*dw), psfp);
  362.                     fputs(" DH\n", psfp);
  363.                 }
  364.                 else if (p->flags & DOTTED) {
  365.                     fputs("0 ", psfp);
  366.                     put_dim(round(sc*dw), psfp);
  367.                     fputs(" DH\n", psfp);
  368.                 }
  369.                 draw_spline(psfp, sc, p->h, p->v, pv, np);
  370.                 fputs("ST\n", psfp);
  371.                 if (p->flags & (DOTTED|DASHED))
  372.                     fputs("SO\n", psfp);
  373.             }
  374.             else {
  375.                 int closed = (np >= 2
  376.                               && pv[0].x == pv[np - 1].x
  377.                               && pv[0].y == pv[np - 1].y);
  378.                 if (p->flags & SHADED) {
  379.                     if (p->shade != 1.0)
  380.                         fprintf(psfp, "%g SG\n", 1 - p->shade);
  381.                     draw_path(psfp, sc, p->h, p->v, pv, np - (closed != 0), 1);
  382.                     fputs("FI\n", psfp);
  383.                     if (p->shade != 1.0)
  384.                         fputs("0 SG\n", psfp);
  385.                 }
  386.                 if (!(p->flags & INVISIBLE)) {
  387.                     if (p->flags & DOTTED) {
  388.                         int i;
  389.                         for (i = 0; i < np - 1; i++) {
  390.                             double x = pv[i+1].x - pv[i].x;
  391.                             double y = pv[i+1].y - pv[i].y;
  392.                             double dist = sqrt(x*x + y*y);
  393.                             double adw;
  394.                             if (dist <= dw)
  395.                                 adw = dist;
  396.                             else 
  397.                                 adw = dist/round(dist/dw);
  398.                             fputs("0 ", psfp);
  399.                             put_dim(round(sc*adw), psfp);
  400.                             fputs(" DH\n", psfp);
  401.                             draw_path(psfp, sc, p->h, p->v, pv + i, 2, 0);
  402.                             fputs("ST\n", psfp);
  403.                         }
  404.                         fputs("SO\n", psfp);
  405.                     }
  406.                     else if (p->flags & DASHED) {
  407.                         int i;
  408.                         for (i = 0; i < np - 1; i++) {
  409.                             double x = pv[i+1].x - pv[i].x;
  410.                             double y = pv[i+1].y - pv[i].y;
  411.                             double dist = sqrt(x*x + y*y);
  412.                             double adw, gw;
  413.                             if (dist <= dw*2.0) {
  414.                                 adw = dist;
  415.                                 gw = 0.0;
  416.                             }
  417.                             else {
  418.                                 int ndashes = (int)(ceil((dist - dw)/(dw*2.0)));
  419.                                 gw = (dist - dw)/ndashes - dw;
  420.                                 adw = dw;
  421.                             }
  422.                             put_dim(round(sc*adw), psfp);
  423.                             putc(' ', psfp);
  424.                             put_dim(round(sc*gw), psfp);
  425.                             fputs(" DH\n", psfp);
  426.                             draw_path(psfp, sc, p->h, p->v, pv + i, 2, 0);
  427.                             fputs("ST\n", psfp);
  428.                         }
  429.                         fputs("SO\n", psfp);
  430.                     }
  431.                     else {
  432.                         draw_path(psfp, sc, p->h, p->v, pv,
  433.                                   np - (closed != 0), closed);
  434.                         fputs("ST\n", psfp);
  435.                     }
  436.                 }
  437.             }
  438.         }
  439.         tpic_object_list = tpic_object_list->next;
  440.         free((char *)p);
  441.     }
  442.     if (r != NO_REGION)
  443.         fputs("GR\n", psfp);
  444.     fputs("EO\n", psfp);
  445. }
  446.  
  447. static void draw_path(psfp, sc, ox, oy, pv, np, closed)
  448. FILE *psfp;
  449. double sc;
  450. integer ox, oy;
  451. struct point *pv;
  452. int np;
  453. int closed;
  454. {
  455.     int i;
  456.     put_dim(ox + round(pv[0].x*sc), psfp);
  457.     putc(' ', psfp);
  458.     put_dim(oy + round(pv[0].y*sc), psfp);
  459.     fputs(" MT\n", psfp);
  460.     for (i = 1; i < np; i++) {
  461.         put_dim(ox + round(pv[i].x*sc), psfp);
  462.         putc(' ', psfp);
  463.         put_dim(oy + round(pv[i].y*sc), psfp);
  464.         fputs(" LT\n", psfp);
  465.     }
  466.     if (closed)
  467.         fputs("CP\n", psfp);
  468. }
  469.  
  470. static void draw_spline(psfp, sc, ox, oy, pv, np)
  471. FILE *psfp;
  472. double sc;
  473. integer ox, oy;
  474. struct point *pv;
  475. int np;
  476. {
  477.     int i;
  478.     put_dim(ox + round(pv[0].x*sc), psfp);
  479.     putc(' ', psfp);
  480.     put_dim(oy + round(pv[0].y*sc), psfp);
  481.     fputs(" MT\n", psfp);
  482.     put_dim(ox + round((pv[0].x+pv[1].x)*sc/2.0), psfp);
  483.     putc(' ', psfp);
  484.     put_dim(oy + round((pv[0].y+pv[1].y)*sc/2.0), psfp);
  485.     fputs(" LT\n", psfp);
  486.     for (i = 1; i < np - 1; i++) {
  487.         put_dim(ox + round((pv[i-1].x + 5*pv[i].x)*sc/6.0), psfp);
  488.         putc(' ', psfp);
  489.         put_dim(oy + round((pv[i-1].y + 5*pv[i].y)*sc/6.0), psfp);
  490.         putc(' ', psfp);
  491.         put_dim(ox + round((5*pv[i].x + pv[i+1].x)*sc/6.0), psfp);
  492.         putc(' ', psfp);
  493.         put_dim(oy + round((5*pv[i].y + pv[i+1].y)*sc/6.0), psfp);
  494.         putc(' ', psfp);
  495.         put_dim(ox + round((pv[i].x+pv[i+1].x)*sc/2.0), psfp);
  496.         putc(' ', psfp);
  497.         put_dim(oy + round((pv[i].y+pv[i+1].y)*sc/2.0), psfp);
  498.         fputs(" CT\n", psfp);
  499.     }
  500.     put_dim(ox + round(pv[np - 1].x*sc), psfp);
  501.     putc(' ', psfp);
  502.     put_dim(oy + round(pv[np - 1].y*sc), psfp);
  503.     fputs(" LT\n", psfp);
  504. }
  505.  
  506. static void draw_ellipse(psfp, sc, ox, oy, cx, cy, rx, ry)
  507. FILE *psfp;
  508. double sc;
  509. integer ox, oy;
  510. integer cx, cy, rx, ry;
  511. {
  512.     put_dim(round(rx*sc), psfp);
  513.     putc(' ', psfp);
  514.     put_dim(round(ry*sc), psfp);
  515.     putc(' ', psfp);
  516.     put_dim(ox + round(sc*cx), psfp);
  517.     putc(' ', psfp);
  518.     put_dim(oy + round(sc*cy), psfp);
  519.     fputs(" EL\n", psfp);
  520. }
  521.  
  522. static void draw_arc(psfp, sc, ox, oy, cx, cy, r, s, e)
  523. FILE *psfp;
  524. double sc;
  525. integer ox, oy;
  526. integer cx, cy, r;
  527. double s, e;
  528. {
  529.     put_dim(ox + round(sc*cx), psfp);
  530.     putc(' ', psfp);
  531.     put_dim(oy + round(sc*cy), psfp);
  532.     putc(' ', psfp);
  533.     put_dim(round(sc*r), psfp);
  534.     fprintf(psfp, " %g %g AR\n", s*180.0/M_PI, e*180.0/M_PI);
  535. }
  536.  
  537. #endif
  538.  
  539. /*
  540. Local Variables:
  541. c-indent-level: 4
  542. c-continued-statement-offset: 4
  543. c-brace-offset: -4
  544. c-argdecl-indent: 0
  545. c-label-offset: -4
  546. tab-width: 4
  547. End:
  548. */
  549.  
  550.